﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestByWire.AttributeHandlers;

namespace TestByWire.Test
{
	[TestClass]
	public class ScopeInformationTests
	{
		private ScopeInformation _target;

		[TestInitialize]
		public void Init()
		{
			ScopeInformation oldInfo = null;
			_target = new ScopeInformation(typeof(ScopeClass).GetMethod("SomeMethod"), oldInfo);
		}


		[TestMethod]
		public void ExtractLocalScope()
		{
			IContainerInteraction[] locals = _target.GetInteractions(Scope.Local);
			Assert.AreEqual(2, locals.Length);

		}

		[TestMethod]
		public void ReuseLocalScope()
		{
			var oldInteractions = _target.GetInteractions(Scope.Local);

			var otherInfo = new ScopeInformation(typeof(ScopeClass).GetMethod("SomeMethod"), _target);
			Assert.AreSame(oldInteractions, otherInfo.GetInteractions(Scope.Local));
		}

		[TestMethod]
		public void ExtractGlobalScope()
		{
			IContainerInteraction[] globals = _target.GetInteractions(Scope.Global);
			Assert.AreEqual(1, globals.Length);
		}

		[TestMethod]
		public void ReuseGlobalScope()
		{
			var oldInteractions = _target.GetInteractions(Scope.Global);

			var otherInfo = new ScopeInformation(typeof(ScopeClass).GetMethod("SomeMethod"), _target);
			Assert.AreSame(oldInteractions, otherInfo.GetInteractions(Scope.Global));
		}

		[TestMethod]
		public void GetInteractions_ShoudlFail_WhenLocalAttributeDeclarationsAreRedundant()
		{
			_target = new ScopeInformation(typeof(ScopeClass).GetMethod("SomeMethod3"), null);
			try
			{
				_target.GetInteractions(Scope.Local);
				Assert.Fail();
			}
			catch (InvalidOperationException)
			{
			}
		}

		[TestMethod]
		public void GetInteractions_ShouldRetrieveAllLocalInteractions_ToScopeCollection()
		{
			IContainerInteraction[] interactions = _target.GetInteractions(Scope.Local);
			Assert.AreEqual(2, interactions.Length);
		}

		[TestMethod]
		public void GetInteractions_ShouldRetrieveAllGlobalInteractions_ToScopeCollection()
		{
			IContainerInteraction[] interactions = _target.GetInteractions(Scope.Global);
			Assert.AreEqual(1, interactions.Length);
		}
	}

	[Serializable]
	[Global]
	internal class ScopeClass
	{
		[Obsolete, Local("Foo"), Local("Bar")]
		public void SomeMethod()
		{ }

		public void SomeMethod2()
		{ }
		[Local("Foo"), Local("Foo")]
		public void SomeMethod3()
		{ }
	}

	internal class GlobalAttribute : Attribute, IContainerInteraction
	{
		public Type RegistrationType
		{
			get { throw new NotImplementedException(); }
		}

		public string RegistrationName
		{
			get { throw new NotImplementedException(); }
		}

		public void Execute(IBuildContext buildContext)
		{
			throw new NotImplementedException();
		}
	}

	[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
	internal class LocalAttribute : Attribute, IContainerInteraction
	{
		public string Name { get; set; }

		public LocalAttribute(String name)
		{
			Name = name;
		}

		public Type RegistrationType
		{
			get { return GetType(); }
		}

		public string RegistrationName
		{
			get { return Name; }
		}

		public void Execute(IBuildContext buildContext)
		{
			throw new NotImplementedException();
		}
	}
}
